﻿Imports System
Imports System.IO
Imports System.Text

Public Class mm_ly

    Const need_ver = "5.1423"                                                                                               '预注册的漠漠版本号
    Const dm_regcode = "cnlanlansky23361f7ae180cfca6d192a5ac2bb029f"            '漠漠VIP账号
    Const dm_verinfo = "lingyu"                                                                                            '漠漠版本附加信息
    Const ini_filename = "mm_ly.ini"
    Const id_filename = "id_card5000.txt"           '身份证文件名

    Private dm As mycx     '定义dm为漠漠对象
    Private mm As mm_diy '定义mm为自定义功能对象
    Private SetFindWidth, SetFindHeight, HwndStart, HwndLogin, HwndPlaying                       '相关参数
    Private ThreadZhuXian, ThreadQiTa, ThreadShiMen                     '相关参数
    Private rootPath As String = Application.StartupPath & "\"          '程序所在主目录
    Private imgPath As String = rootPath & "\Resources\"                  '程序附件所在目录
    Private baseDmPath As String = imgPath                                          '漠漠插件,字体所在目录,等同于程序附件所在目录
    Private gamePath As String                  '游戏执行文件路径
    Private accountPath As String              '游戏账户文件路径
    Private isLogStart                                   '是否开启日志
    Private yzmServerSn As String            'YZM答题SN
    Private mmDatiIp As String                   '内网答题IP
    Private accountArr As Array                  '游戏账号数组, 每一个账号

    '●●●●●●●●●●●●●●●●●●●●●●●●●●●脚本开始●●●●●●●●●●●●●●●●●●●●●●●●●●●
    '右侧寻路字体绿色:00fc00-000000|60fc60-000000
    '右侧寻路字体白色:f8fcf8-000000
    '右侧提交物品/[九生花]淡蓝:78fcf8-000000|00fcf8-000000
    '右侧活动字体紫色:f800f8-000000 
    '底部可升级颜色:F4BE6C-042654
    '修行字体颜色:f8fc00-000000|00fcf8-000000|F8D424-002024
    '**第一次过程中,寻物F8D424-002024


    Private Sub mm_ly_Load(sender As Object, e As EventArgs) Handles MyBase.Load
        If Not (init()) Then
            Console.WriteLine("程序初始化错误,请检查日志! ")
        End If
    End Sub

    Private Function init() As Boolean  '程序初初始化操作, 释放资源文件,注册漠漠插件,读取配置文件,读取账号, 如果有错误则返回false
        SetFindWidth = 1024
        SetFindHeight = 768
        Console.WriteLine("当前程序所在目录:" & rootPath)
        If Not (File.Exists(imgPath & "sky.dll")) Then    '判断sky.dll是否存在,不存在则报错退出初始化
            MsgBox("程序初始化失败!")
            Return False
        End If
        If regDm(dm_regcode, dm_verinfo) Then   '尝试注册漠漠,如果注册成功则继续初始化
            dm.SetPath(baseDmPath)
            dm.SetDict(0, "font.txt")
            dm.SetShowErrorMsg(0)
            If readini() Then                                        '读取配置文件
                Console.WriteLine("读取配置文件成功!")
            Else
                Console.WriteLine("请查看日志!")
            End If
        End If
        If txtIdPath.Text <> "" Then    '如果账号文件路径不为空的话,则加载游戏账号
            If readAccount() Then
                Console.WriteLine("加载游戏账号成功!")
            End If
        End If
        Return True
    End Function



    Private Function readini() As Boolean   '读取配置文件函数
        Dim iniFilePath As String
        iniFilePath = rootPath & ini_filename
        Try  '如果配置文件不存在的话,尝试创建配置文件, 创建失败函数退出返回 false
            If Not (File.Exists(iniFilePath)) Then
                Dim fs As FileStream = File.Create(iniFilePath)   '创建配置文件
                'Dim info As Byte() = New UTF8Encoding(True).GetBytes("This is some text in the file.")  '得先做转换
                'fs.Write(info, 0, info.Length)        '这是filestrem类写入内容的方法
                fs.Close()   '通过file.create方法创建的文件默认是打开的,如果想让别的程序能操作就得先关闭文件
            Else
                gamePath = dm.ReadIni("base", "gamePath", iniFilePath)
                accountPath = dm.ReadIni("base", "accountPath", iniFilePath)
                yzmServerSn = dm.ReadIni("base", "yzmServerSn", iniFilePath)
                mmDatiIp = dm.ReadIni("base", "mmDatiIp", iniFilePath)
                txtGamePath.Text = gamePath
                txtIdPath.Text = accountPath
                txtDatiIp.Text = yzmServerSn
                txtDatiIp.Text = mmDatiIp
            End If

        Catch ex As Exception
            Console.WriteLine(ex)
            Return False
        End Try

        Return True
    End Function

    Private Function saveini() As Boolean    '保存配置文件函数
        Dim iniFilePath As String
        iniFilePath = rootPath & ini_filename
        Try  '
            If File.Exists(iniFilePath) Then
                gamePath = txtGamePath.Text
                accountPath = txtIdPath.Text
                yzmServerSn = txtDatiIp.Text
                mmDatiIp = txtDatiIp.Text
                dm.WriteIni("base", "gamePath", gamePath, iniFilePath)
                dm.WriteIni("base", "accountPath", accountPath, iniFilePath)
                dm.WriteIni("base", "yzmServerSn", yzmServerSn, iniFilePath)
                dm.WriteIni("base", "mmDatiIp", mmDatiIp, iniFilePath)
            End If
        Catch ex As Exception
            Console.WriteLine(ex)
            Return False
        End Try
        Return True
    End Function

    Private Function regDm(ByVal dm_regcode As String, ByVal dm_verinfo As String) As Boolean
        Dim ver As String, oldDmPath As String, testDmVip As Integer
        'Console.WriteLine(ws)
        Shell("regsvr32 atl.dll /s") ' 插件需要用到atl系统库,有些XP精简系统会把atl.dll精简掉. 为了防止注册失败，这里手动注册一下atl.dll
        'Shell("regsvr32 " & basePath & "sky.dll  /u /s")
        Shell("regsvr32 " & baseDmPath & "sky.dll  /s")
        Delay(500)
        dm = New mycx   '创建漠漠对象
        ver = dm.Ver
        If ver <> need_ver Then  '判断预注册版本和当前版本是否一致
            If ver <> "" Then '判断是否得到版本信息,及sky.dll是否注册成功
                oldDmPath = dm.GetBasePath() '得到系统已经注册的sky.dll的路径
                dm = Nothing
                Shell("regsvr32 " & oldDmPath & "sky.dll  /u /s") '卸载系统已经注册的sky.dll
                Delay(200)
                ver = ""
                dm = New mycx '再次创漠漠对象
                ver = dm.Ver()
                If ver = "" Then
                    Console.WriteLine("卸载成功")
                Else
                    MsgBox("卸载失败,当前版本为:【" & ver & "】,路径:【" & dm.GetBasePath() & "】")
                    Return False
                End If
            End If
            Shell("regsvr32 " & baseDmPath & "sky.dll  /s")  '注册指定版本
            Delay(500)
            ver = ""
            dm = New mycx '卸载成功后再次创建漠漠对象
            ver = dm.Ver()
            If ver <> need_ver Then
                MsgBox("初始化,当前漠漠版本为:【" & ver & "】,路径:【" & dm.GetBasePath() & "】")
                Return False
            End If
        End If
        Console.WriteLine("漠漠版本: " & ver)
        testDmVip = dm.Reg(dm_regcode, dm_verinfo) '开始注册收费功能.
        Select Case testDmVip
            Case -1
                Console.WriteLine("无法连接网络,(可能防火墙拦截,如果可以正常访问大漠插件网站，那就可以肯定是被防火墙拦截)")
            Case -2
                Console.WriteLine("进程没有以管理员方式运行. (出现在win7 win8 vista 2008.建议关闭uac")
            Case 0
                Console.WriteLine("失败(未知错误)")
            Case 1
                Console.WriteLine("漠漠VIP注册成功!")
            Case 2
                Console.WriteLine("余额不足")
            Case 3
                Console.WriteLine("绑定了本机器，但是账户余额不足50元.")
            Case 4
                Console.WriteLine(": 注册码错误")
            Case 5
                Console.WriteLine(": 你的机器或者IP在黑名单列表中或者不在白名单列表中.")
            Case 6
                Console.WriteLine(": 非法使用插件.")
            Case 7
                Console.WriteLine(": 你的帐号因为非法使用被封禁.")
            Case -8
                Console.WriteLine(": 版本附加信息长度超过了10()")
            Case -9
                Console.WriteLine(": 版本附加信息里包含了非法字母.")
        End Select
        If testDmVip <> 1 Then
            MsgBox("漠漠VIP注册失败! 请检查日志!")
            Return False
        End If
        Return True
    End Function

    Private Sub Delay(ByVal Interval As Double)  'Interval单位为毫秒
        Dim time As DateTime = DateTime.Now
        Dim Span As Double = Interval * 10000  '因为时间是以100纳秒为单位
        While ((DateTime.Now.Ticks - time.Ticks) < Span)
            Application.DoEvents()
        End While
    End Sub

    Private Sub btnStart_Click(sender As Object, e As EventArgs) Handles btnStart.Click
        Dim i As Integer, accountSum As Integer
        Dim userName As String, password As String, serverOne As String, serverTwo As String
        Dim nextStep As Boolean
        '游戏启动
        accountSum = dgwAccount.Rows.Count - 1  '取得当前加载游戏账号的总数 
        userName = "" : password = "" : serverOne = "" : serverTwo = ""
        For i = 0 To accountSum
            HwndStart = dm.FindWindowSuper("灵域", 0, 0, "#32770", 2, 0)              '句柄:启动窗口
            HwndLogin = dm.FindWindowSuper("灵域", 0, 0, "QWidget", 2, 0)         '句柄:登录窗口
            HwndPlaying = dm.FindWindowSuper("灵域 ", 0, 1, "TL_LY_WINDOW", 2, 1) '句柄:游戏中窗口
            nextStep = readCurrentAccountTxt(i, userName, password, serverOne, serverTwo)  '读取当前运行游戏账号
            If nextStep Then
                nextStep = gameStart(gamePath)    '启动游戏
            End If
            If nextStep Then
                Console.WriteLine("游戏启动成功!")
                nextStep = gameLogin(i, userName, password, serverOne, serverTwo)   '尝试游戏登陆, 传入当前账号在加载的游戏账号的行号
            End If
            If nextStep Then
                Console.WriteLine("游戏登陆成功!")
            End If
            Exit For  '调试用,登陆一个账号就退出

        Next

    End Sub

    Private Function gameLogin(ByVal rowNum, userName, password, serverOne, serverTwo) As Boolean
        Dim mm As mm_diy
        Dim i, imgX, imgY, idCards, idRecord, idName, idNumber, handlePic, result, idArr
        'idards 存储所有身份证记录, idRecord  记录单挑身份证信息, idName 身份证名字, idNumber 身份证号
        mm = New mm_diy(dm)
        For i = 0 To 100    '判断登陆窗口出现
            HwndLogin = dm.FindWindowSuper("灵域", 0, 0, "QWidget", 2, 0) '句柄: 登录窗口
            If HwndLogin <> 0 Then
                Exit For
            ElseIf i = 100 Then
                Return False
            End If
            dm.Delay(100)
        Next
        mm.WaitBindEx("登录窗口", HwndLogin, 10)
        Do While dm.FindWindowSuper("灵域 ", 0, 1, "TL_LY_WINDOW", 2, 1) = 0
            mm.WaitImg("寻找登录按钮", "1_登录1.bmp|1_登录2.bmp", 10, SetFindWidth, SetFindWidth, imgX, imgY)
            mm.LClick(545, 310, 10, 5, 0) '点击账号输入框,范围10/5
            dm.Delay(Random(800, 1500))
            For i = 1 To 20 '按退格键20次,用作删除上次登录的账号
                dm.KeyPress(8)
                dm.Delay(Random(40, 80))
            Next
            mm.KeyPressStr(userName)  '输入账号
            dm.Delay(Random(500, 1000))
            mm.LClick(465, 345, 120, 12, 0)  '点击密码输入框,范围 120/12
            mm.KeyPressStr(password)  '输入密码
            dm.Delay(Random(500, 1000))
            mm.LClick(468, 438, 30, 10, 0)  ' 点击<登录>, 范围 60/27

            If mm.WaitImg("验证码", "2_0_验证码.bmp", 2, SetFindWidth, SetFindWidth, imgX, imgY) <> -1 Then
                Do
                    handlePic = dm.FaqCapture(341, 404, 451, 444, 100, 0, 0)
                    Delay(200)
                    result = Split(dm.FaqSend(mmDatiIp, handlePic, 2, 10 * 1000), ":")
                    Console.WriteLine(result(0) & "-------" & result(1))
                    If result(0) = "OK" Then
                        mm.LClick(358, 376, 20, 8, 1)
                        dm.Delay(500)
                        dm.KeyPressStr(result(1), 30)
                    End If
                    dm.Delay(1000)
                    mm.LClick(493, 474, 30, 8, 1)
                    dm.Delay(1000)
                    If mm.WaitImg("验证码", "2_0_验证码.bmp", 2, SetFindWidth, SetFindWidth, imgX, imgY) = -1 Then
                        Exit Do
                    End If
                Loop
            End If

            If mm.WaitImg("寻找提交注册按钮", "2_0_提交注册信息.bmp", 2, SetFindWidth, SetFindWidth, imgX, imgY) <> -1 Then

                Do While mm.WaitImg("重新登录游戏", "2_0_重新登录游戏.bmp", 2, SetFindWidth, SetFindWidth, imgX, imgY) = -1
                    '开始处理身份证文本
                    idCards = File.ReadAllLines(imgPath & id_filename)
                    idRecord = idCards(Random(0, UBound(idCards) - 1))
                    idArr = Split(idRecord, "|")
                    idName = idArr(0) : idNumber = idArr(1)
                    Console.WriteLine(idName & " : " & idNumber)
                    dm.Delay(Random(500, 1000))
                    '以下处理输入身份证名字
                    mm.LClick(485, 407, 40, 12, 0)   '单击输入身份证名字INPUT框
                    dm.SetClipboard(idName) ' 身份证名字放到剪切板,用来后面粘贴
                    For i = 1 To Random(15, 20)   '随机按15到20次 退格键
                        dm.KeyPress(8)
                        dm.Delay(Random(50, 200))
                    Next
                    Delay(500)
                    dm.KeyDown(17)               '按下Ctrl键
                    Delay(Random(300, 500))
                    dm.KeyPress(86)               '键入V键
                    Delay(Random(100, 150))
                    dm.KeyUp(17)                  '松开 Ctrl键   完成CTRL+ V 粘贴过程

                    '以下处理输入身份证名字过程
                    Delay(Random(1000, 1500))
                    mm.LClick(524, 445, 18, 15, 0)  '单击输入身份证号码INPUT框
                    For i = 1 To Random(20, 30)
                        dm.KeyPress(8)
                        dm.Delay(Random(50, 150))
                    Next
                    dm.Delay(Random(500, 1000))
                    mm.KeyPressStr(idNumber)  '输入身份证

                    If mm.WaitImg("寻找提交注册按钮", "2_0_提交注册信息.bmp", 2, SetFindWidth, SetFindWidth, imgX, imgY) <> -1 Then
                        dm.Delay(Random(500, 1000))
                        mm.LClick(imgX, imgY, 100, 10, 1)
                    End If
                    mm.WaitImg("寻找输入错误的确定", "2_0_确定.bmp", 3, SetFindWidth, SetFindWidth, imgX, imgY)
                    mm.LClick(imgX, imgY, 30, 9, 1)
                Loop
                dm.Delay(1000)

                If mm.WaitImg("重新登录游戏", "2_0_重新登录游戏.bmp", 2, SetFindWidth, SetFindWidth, imgX, imgY) <> -1 Then
                    mm.LClick(imgX, imgY, 80, 9, 1)
                End If
            End If
        Loop
        Return True

    End Function

    Private Function gameStart(ByVal gamePath As String) As Boolean  '启动游戏
        Dim mm As mm_diy, imgX, imgy
        Dim i As Integer, result
        mm = New mm_diy(dm)
        'mm.setPath(baseDmPath)
        Try
            If HwndStart + HwndLogin + HwndPlaying = 0 Then '判断所有窗口是否存在
                dm.RunApp(gamePath, 1) '启动游戏
                For i = 1 To 100
                    HwndStart = dm.FindWindowSuper("灵域", 0, 0, "#32770", 2, 0)              '句柄:启动窗口
                    If HwndStart <> 0 Then
                        Exit For
                    End If
                    Delay(100)
                Next
                If mm.WaitBindEx("启动窗口", HwndStart, 10) = 1 Then
                    Console.WriteLine("启动【" & gamePath & " 】运行中~~ 句柄:【" & HwndStart & "】")
                    mm.WaitImg("寻找进入按钮", "1_进入.bmp", 10, SetFindWidth, SetFindWidth, imgX, imgy)  '返回找到的进入按钮坐标, 切记这里 imgx, imgy不能定义为整数类型,否则不能传递返回值
                    mm.LClick(imgX, imgy, 80, 30, 0) '点击<进入>
                End If
            End If
        Catch ex As Exception
            Console.WriteLine("启动游戏失败!  " & ex.Message)
            Return False
        End Try
        Return True
    End Function

    Private Function readCurrentAccountTxt(ByVal rowNum As Integer, ByRef userName As String, ByRef password As String, ByRef serverOne As String, ByRef serverTwo As String) As Boolean
        userName = dgwAccount.Item(0, rowNum).Value
        password = dgwAccount.Item(1, rowNum).Value
        serverOne = dgwAccount.Item(2, rowNum).Value
        serverTwo = dgwAccount.Item(3, rowNum).Value
        Console.WriteLine("【" & rowNum & "】【账号:" & userName & "】 【密码:" & password & "】 【大区:" & serverOne & "】 【小区:" & serverTwo & "】")
        If userName <> "" And password <> "" And serverOne <> "" And serverTwo <> "" Then
            Return True
        Else
            Console.WriteLine("读取账号为空!")
            Return False
        End If
    End Function

    Private Function readAccountTxt() As Boolean               '
        Dim accountRow()   '存取每一行账号
        Dim accountLine As String, i As Integer, j As Integer
        Try                                                                 '尝试从accountPath 文件中读取游戏账号
            accountArr = File.ReadAllLines(accountPath)
        Catch ex As Exception
            Console.WriteLine(ex)
            MsgBox("读取游戏账号失败!")
            Return False
        End Try

        For i = 0 To UBound(accountArr)
            accountLine = accountArr(i)
            accountRow = Split(accountLine, "|")
            ' Console.WriteLine(accountLine)
            dgwAccount.Rows.Add()
            'dgwAccount(1, i).Value = "1"
            For j = 0 To UBound(accountRow)
                dgwAccount.Item(j, i).Value = accountRow(j)
                'dgwAccount(j, i).Value = accountRow(j)
            Next
        Next
        Console.WriteLine("表格中账号的个数: " & dgwAccount.Rows.Count)

        Return True
    End Function

    Private Function Random(ByVal Min, ByVal Max) As Integer
        Dim result As Integer
        Randomize()
        result = Int((Max - Min + 1) * Rnd() + Min)
        Return result
    End Function

    Private Sub btnGamePath_Click(sender As Object, e As EventArgs) Handles btnGamePath.Click
        OpenFileDialogGamePath.ShowDialog()
        txtGamePath.Text = OpenFileDialogGamePath.FileName

    End Sub

    Private Sub btnIdPath_Click(sender As Object, e As EventArgs) Handles btnIdPath.Click
        OpenFileDialogIdPath.ShowDialog()
        txtIdPath.Text = OpenFileDialogIdPath.FileName

    End Sub

    Private Sub mm_ly_closed(sender As Object, e As System.EventArgs) Handles MyBase.Closed
        'mm.UnBindWindow()
        'mm = Nothing
    End Sub

    Private Sub btnSaveini_Click(sender As Object, e As EventArgs) Handles btnSaveini.Click
        If txtGamePath.Text <> "" And txtIdPath.Text <> "" And (txtDatingSn.Text <> "" Or txtDatiIp.Text <> "") Then
            If saveini() Then
                MsgBox("配置保存成功!")
            Else
                MsgBox("配置保存失败!请检查日志!")
            End If
        End If
    End Sub


    Private Sub btnTest_Click(sender As Object, e As EventArgs) Handles btnTest.Click
        Dim hwnd, hwnd1, mm_ret
        mm = New mm_diy(dm)
        'mm.setPath(baseDmPath)
        'hwnd1 = dm.FindWindow("Notepad", "")
        'hwnd = dm.FindWindowEx(hwnd1, "Edit", 0)
        'mm_ret = dm.BindWindow(hwnd1, "normal", "normal", "normal", 0)
        'dm.SetWindowState(hwnd, 12)
        'dm.SendString(hwnd, "风骚啊风骚")
        'mm.KeyPressStr("feng sao a feng sao ")
        'dm.SendString(hwnd, "调用完自定义功能对象之后")
        Dim idCards, idRecord, idArr, idName, idNumber
        idCards = File.ReadAllLines(imgPath & id_filename)
        idRecord = idCards(Random(0, UBound(idCards) - 1))
        idArr = Split(idRecord, "|")
        idName = idArr(0) : idNumber = idArr(1)
        Console.WriteLine(idName & " : " & idNumber)
    End Sub


    Private Sub btnLoadAccount_Click(sender As Object, e As EventArgs) Handles btnLoadAccount.Click
        readAccountTxt()
    End Sub
End Class
